package com.dy.yunying.biz.service.yyz.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dy.yunying.api.base.BaseDto;
import com.dy.yunying.api.constant.Constant;
import com.dy.yunying.api.entity.GameAppointment;
import com.dy.yunying.api.enums.RedisNameEnum;
import com.dy.yunying.api.req.yyz.*;
import com.dy.yunying.api.resp.yyz.GameAppointmentExportRes;
import com.dy.yunying.api.resp.yyz.GameAppointmentPageRes;
import com.dy.yunying.biz.config.YunYingProperties;
import com.dy.yunying.biz.dao.manage.GameAppointmentMapper;
import com.dy.yunying.biz.service.yyz.GameAppointmentService;
import com.dy.yunying.biz.service.yyz.SendMassageService;
import com.dy.yunying.biz.utils.BuildExcelDocument;
import com.dy.yunying.biz.utils.DateUtils;
import com.google.api.client.util.Lists;
import com.pig4cloud.pig.common.core.util.R;
import com.sjda.framework.common.utils.HttpClient;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 游戏预约表
 *
 * @author kongyanfang
 * @version 2022-01-17 17:14:29
 * table: game_appointment
 */
@Log4j2
@Service("gameAppointmentService")
@RequiredArgsConstructor
public class GameAppointmentServiceImpl extends ServiceImpl<GameAppointmentMapper, GameAppointment> implements GameAppointmentService
{

	private final GameAppointmentMapper gameAppointmentMapper;

	private final SendMassageService sendMassageService;
	@Autowired
	private RedisTemplate<String, String> redisTemplate;

	@Autowired
	private YunYingProperties yunYingProperties;

	@Override
	public R getPage(GameAppointmentQueryReq req) {
		IPage<GameAppointmentPageRes> iPage = gameAppointmentMapper.selectGameAppointmentPage(req);
		List<GameAppointmentPageRes> records = iPage.getRecords();
		records.forEach(gameAppointmentPageRes -> {
			if(gameAppointmentPageRes.getAppointDevice()==1){
				gameAppointmentPageRes.setAppointDeviceName("IOS");
			}else {
				gameAppointmentPageRes.setAppointDeviceName("android");
			}
			if(gameAppointmentPageRes.getAppointSource()==1){
				gameAppointmentPageRes.setAppointSourceName("PC");
			}else {
				gameAppointmentPageRes.setAppointSourceName("H5");
			}
			gameAppointmentPageRes.setGameName(gameAppointmentMapper.getGameName(gameAppointmentPageRes.getType().toString()));
		});
		return R.ok(iPage);
	}

	@Override
	public R addAppointment(GameAppointmentReq req) {
		try {
			//短信验证码验证
			R x = checkSmgCode(req.getMobile(), req.getYzm(), req.getCodeType(), req.getRandom());
			if (x != null) return x;
			log.info("短信验证码验证通过");
			//查询手机号唯一
			GameAppointment appointment = this.getOne(Wrappers.<GameAppointment>lambdaQuery().eq(GameAppointment::getType,req.getType()).eq(GameAppointment::getMobile, req.getMobile()));
			if (Objects.nonNull(appointment)) {
				log.info("手机号已存在，不能预约");
				return R.failed(null, 1, "手机号已存在，不能重复预约");
			}
			log.info("手机号不存在，可以预约");
			//添加入库
			appointment = new GameAppointment();
			appointment.setMobile(req.getMobile());
			appointment.setPgid(1L);
			appointment.setType(req.getType());
			appointment.setAppointDevice(req.getDevice());
			appointment.setAppointSource(req.getCodeType());
			appointment.setAppointTime(new Date());
			appointment.setCreateTime(new Date());
			this.save(appointment);
		} catch (Exception e) {
			log.error("手机号预约异常：{}", e);
			return R.failed(null, 6, "系统异常");
		}
		return R.ok(null, "手机号预约成功");
	}

	@Override
	public R total() {
		//数据库预约人数
		Integer total = gameAppointmentMapper.selectTotal();
		//每5分钟增长一次
		Integer accumulative = 0;
		if (yunYingProperties.isOpen()) {
			String timeKey = redisTemplate.opsForValue().get(RedisNameEnum.TIME_KEY.get(null));
			String acctKey = redisTemplate.opsForValue().get(RedisNameEnum.ACCUMULATIVE_KEY.get(null));
			if (StringUtils.isBlank(timeKey)) {
				if (StringUtils.isBlank(acctKey)) {
					accumulative = accumulative + Integer.valueOf(yunYingProperties.getNumber());
				} else {
					accumulative = Integer.valueOf(acctKey) + Integer.valueOf(yunYingProperties.getNumber());
				}
				redisTemplate.opsForValue().set(RedisNameEnum.ACCUMULATIVE_KEY.get(null), accumulative.toString());
				redisTemplate.opsForValue().set(RedisNameEnum.TIME_KEY.get(null), String.valueOf(System.currentTimeMillis()), 5, TimeUnit.MINUTES);
			} else {
				accumulative = Integer.valueOf(acctKey);
			}
		}
		//taptap预约人数
		Long subscribe = yunYingProperties.getSubscribe();
//		this.getTaptapNum();
//		String subscribe_hscj = redisTemplate.opsForValue().get(RedisNameEnum.TAPTAP_HSCJ_KEY.get(null));
//		if (StringUtils.isNotBlank(subscribe_hscj)) {
//			subscribe = Integer.valueOf(subscribe_hscj);
//		}
		total = total + subscribe.intValue() + accumulative;
		return R.ok(total);
	}

	@Override
	public R allTotal(GameAppointmentReq req) {
		//数据库预约人数
		Integer accumulative = 0;
		Long total = gameAppointmentMapper.selectAllTotal(req);
		Long ruleTotal = gameAppointmentMapper.selectRuleAllTotal(req);
		accumulative=accumulative+total.intValue()+ruleTotal.intValue();

		return R.ok(accumulative);
	}

	/***
	 * taptap预约人数
	 * @return
	 */
	private boolean getTaptapNum() {
		String url = yunYingProperties.getTapTapUrl();
		Map<String, String> queryParas = new HashedMap();
		queryParas.put("X-UA", yunYingProperties.getTapTapParam());
		Map<String, String> headers = new HashedMap();
		headers.put("accept", "*/*");
		headers.put("connection", "Keep-Alive");
		headers.put(HttpClient.ContentType.JSON.getContype(), HttpClient.ContentType.JSON.getContext());
		String result = HttpClient.get(url, queryParas, headers);
		log.info("调用TapTap接口，获取预约人数 返回，resp:{}", result);
		JSONObject obj;
		if (StringUtils.isBlank(result)) {
			log.error("调用TapTap接口，获取预约人数失败，result:{}", "为空");
			return false;
		} else {
			obj = BaseDto.fromJson(result, JSONObject.class);
			if (Objects.isNull(obj) || !obj.containsKey("success") || !obj.getBoolean("success")) {
				log.error("调用TapTap接口，获取预约人数失败，success:{}", "false或不存在");
				return false;
			}
			JSONObject data = BaseDto.fromJson(obj.getString("data"), JSONObject.class);
			if (Objects.isNull(data) || !data.containsKey("stat")) {
				log.error("调用TapTap接口，获取预约人数失败，data:{}", "为空或stat不存在");
				return false;
			}
			JSONObject stat = BaseDto.fromJson(data.getString("stat"), JSONObject.class);
			if (Objects.isNull(stat) || !stat.containsKey("reserve_count")) {
				log.error("调用TapTap接口，获取预约人数失败，stat:{}", "为空或reserve_count不存在");
				return false;
			}
			Integer subscribe = stat.getInteger("reserve_count");
			if (subscribe > 0) {
				log.info("调用TapTap接口，获取预约人数成功");
				redisTemplate.opsForValue().set(RedisNameEnum.TAPTAP_HSCJ_KEY.get(null), subscribe.toString());
				return true;
			}
		}
		return false;
	}

	@Override
	public R batchMsg(GameAppointmentReq req) {
		if(Objects.isNull(req.getType())){
			req.setType(Constant.TYPE_1);
		}
		String id=req.getId();
		String mobile = req.getMobile();
		Integer device  =req.getDevice();
		Integer type=req.getType();
		Date appointStartTIme=req.getAppointStartTime();
		Date appointEndTime=req.getAppointEndTime();
		List<GameAppointment> gameAppointmentList= Lists.newArrayList();
		LambdaQueryWrapper<GameAppointment> queryWrapper=new LambdaQueryWrapper<GameAppointment>().eq(GameAppointment::getDeleted,Constant.DEL_NO).eq(GameAppointment::getType,type);
		if(StringUtils.isNotBlank(id)){
			List<String> idList= Arrays.asList(id.split(","));
			queryWrapper=queryWrapper.in(GameAppointment::getId,idList);
		}
		if(StringUtils.isNotBlank(mobile)){
			List<String> mobileList= Arrays.asList(mobile.split(","));
			queryWrapper=queryWrapper.in(GameAppointment::getMobile,mobileList);
		}
		if(Objects.nonNull(device)){
			queryWrapper=queryWrapper.eq(GameAppointment::getAppointDevice,device);
		}
		if(Objects.nonNull(appointStartTIme)){
			queryWrapper=queryWrapper.ge(GameAppointment::getAppointTime,appointStartTIme);
		}
		if(Objects.nonNull(appointEndTime)){
			queryWrapper=queryWrapper.le(GameAppointment::getAppointTime,appointEndTime);
		}
		gameAppointmentList=this.list(queryWrapper);
		return sendMassageService.batchSendMsg(gameAppointmentList, req.getSendType());
	}

	@Override
	public R getGameList() {
		List<GameCodeReq> gameCodeReqs = gameAppointmentMapper.selectGameList();
		return R.ok(gameCodeReqs);
	}

	@Override
	public R sendCodeList() {
		List<SendTemplateCodeReq> sendTemplateCodeReq= gameAppointmentMapper.selectTemplateList();
		return R.ok(sendTemplateCodeReq);
	}

	@Override
	public void export(HttpServletResponse response, GameAppointmentQueryReqList req) {
		List<GameAppointmentQueryList> list = gameAppointmentMapper.selectGameAppointmentList(req);
		List<GameAppointmentExportRes> gameAppointmentExportResList = new ArrayList<>();
		list.forEach(gameAppointmentQueryList -> {
			GameAppointmentExportRes gameAppointmentExportRes= new GameAppointmentExportRes();
			gameAppointmentExportRes.setId(gameAppointmentQueryList.getId());
			gameAppointmentExportRes.setMobile(gameAppointmentQueryList.getMobile());
			if(gameAppointmentQueryList.getAppointDevice()==1){
				gameAppointmentExportRes.setAppointDeviceName("IOS");
			}else {
				gameAppointmentExportRes.setAppointDeviceName("android");
			}
			if(gameAppointmentQueryList.getAppointSource()==1){
				gameAppointmentExportRes.setAppointSourceName("PC");
			}else {
				gameAppointmentExportRes.setAppointSourceName("H5");
			}
			gameAppointmentExportRes.setGameName(gameAppointmentMapper.getGameName(gameAppointmentQueryList.getType().toString()));
			gameAppointmentExportRes.setAppointTime(gameAppointmentQueryList.getAppointTime());
			gameAppointmentExportResList.add(gameAppointmentExportRes);
		});
		//查询区服
		String head = "主键,游戏名称,预约手机号,手机系统,预约来源,预约时间";
		String column ="id,gameName,mobile,appointDeviceName,appointSourceName,appointTime";
		String fileName = "预约用户表-"+ DateUtils.getCurrentTimeNoUnderline() + ".xlsx";
		try {
			BuildExcelDocument.exportExcelData(response,gameAppointmentExportResList,head,fileName,column);
		} catch (Exception e) {
			log.error("导出失败: Detail and error:{} and errorMessage:{}", e, e.getMessage());
		}
	}


	/***
	 * 短信验证码验证
	 * @param mobile
	 * @param yzm
	 * @return
	 */
	private R checkSmgCode(String mobile, String yzm, Integer codeType, String random) {
		//目前只做短信验证码判断，图像验证码不校验，验证码目前只控制短信验证码的获取
		//判断验证码是否过期
		String timeKey = redisTemplate.opsForValue().get(RedisNameEnum.SMS_CODE_TIME.get(mobile) + "_" + codeType + "_" + random);
		if (StringUtils.isNotBlank(timeKey)) {
			Long time = Long.parseLong(timeKey);
			long now = System.currentTimeMillis();
			if (time == null || now - time > 5 * 60 * 1000) {
				log.info("短信验证码已过期");
				return R.failed(null, 3, "短信验证码已过期");
			}
		}
		//短信验证码
		String smsYzm = redisTemplate.opsForValue().get(RedisNameEnum.SMS_CODE.get(mobile) + "_" + codeType + "_" + random);
		if (StringUtils.isBlank(smsYzm) || !smsYzm.equals(yzm)) {
			log.info("短信验证码错误或已失效");
			return R.failed(null, 4, "短信验证码错误或已失效");
		}
		if (!smsYzm.equals(yzm)) {
			log.info("短信验证码错误");
			return R.failed(null, 5, "短信验证码错误");
		}
		//验证码验证成功，删除验证码缓存设置
		redisTemplate.delete(RedisNameEnum.RANDOM_KEY.get(random));
		//redisTemplate.delete(RedisNameEnum.SCAPTCHA_KEY.get(codeType) + "_" + random);
		redisTemplate.delete(RedisNameEnum.SMS_CODE.get(mobile) + "_" + codeType + "_" + random);
		redisTemplate.delete(RedisNameEnum.SMS_CODE_TIME.get(mobile) + "_" + codeType + "_" + random);
		return null;
	}

}


